package com.tea.modules.java8.thread.completable;

import com.google.common.collect.Lists;
import com.tea.modules.java8.thread.future.Workable;

import java.util.ArrayList;
import java.util.concurrent.CompletableFuture;

import static com.tea.modules.java8.thread.completable.CompletableUtilities.*;


/**
 * com.tea.modules.java8.thread.completable
 *
 * @author jaymin
 * @since 2022/4/15
 */
public class DualCompletableOperations {
    static CompletableFuture<Workable> cfA, cfB;

    /**
     * 初始化两个CompletableFuture
     */
    static void init() {
        cfA = Workable.make("A", 0.15);
        cfB = Workable.make("B", 0.10); // Always wins
    }

    /**
     * 等待线程完成
     */
    static void join() {
        cfA.join();
        cfB.join();
        System.out.println("*****************");
    }

    public static void main(String[] args) {
        // B->either->A
        // 意思是跑完B再跑runAfterEither再跑A
        init();
        voidResult(cfA.runAfterEitherAsync(cfB, () -> System.out.println("runAfterEither")));
        join();

        // B->A->both
        init();
        voidResult(cfA.runAfterBothAsync(cfB, () -> System.out.println("runAfterBoth")));
        join();

        //  B->applyToEither->B->A
        init();
        showResult(cfA.applyToEitherAsync(cfB, w -> {
            System.out.println("applyToEither: " + w);
            return w;
        }));
        join();

        // 当任意一个CompletableFuture完成的时候，action这个消费者就会被执行
        init();
        showResult(cfA.acceptEitherAsync(cfB, w -> {
            System.out.println("acceptEither: " + w);
        }));
        join();

        // B->A->thenAcceptBoth
        init();
        voidResult(cfA.thenAcceptBothAsync(cfB, (w1, w2) -> {
            System.out.println("thenAcceptBoth: "
                    + w1 + ", " + w2);
        }));
        join();

        //
        init();
        showResult(cfA.thenCombineAsync(cfB, (w1, w2) -> {
            System.out.println("thenCombine: "
                    + w1 + ", " + w2);
            return w1;
        }));
        join();

        // 执行一个的时候跑action
        init();
        CompletableFuture<Workable>
                cfC = Workable.make("C", 0.08),
                cfD = Workable.make("D", 0.09);
        CompletableFuture.anyOf(cfA, cfB, cfC, cfD)
                .thenRunAsync(() ->
                        System.out.println("anyOf"));
        join();

        // 所有人完成再触发
        init();
        cfC = Workable.make("C", 0.08);
        cfD = Workable.make("D", 0.09);
        ArrayList<CompletableFuture<Workable>> completableFutures = Lists.newArrayList(cfA, cfB, cfC, cfD);
        CompletableFuture.allOf(completableFutures.toArray(new CompletableFuture[]{}))
                .thenRunAsync(() ->
                        System.out.println("allOf"));
        join();
    }
}